from PyQt5.QtWidgets import (
    QMainWindow, QVBoxLayout, QHBoxLayout, QWidget, QPushButton, QLineEdit, QSplitter, QMenu,
    QLabel, QComboBox, QTableWidget, QTableWidgetItem, QMessageBox, QHeaderView, QTextEdit, QCheckBox, QDialog
)
from PyQt5.QtCore import Qt, pyqtSlot, QThreadPool
from PyQt5.QtGui import QColor, QIcon, QPixmap
from config.config_manager import ConfigManager
from gui.threads.main_window_connectors_pools import DatabaseConnectorPool
from gui.widgets.db_connection_dialog import ConnectionDialog
from gui.widgets.sys_setting_dialog import SettingsDialog
from gui.threads.table_match_worker_thread import TableMatchWorker
from gui.threads.data_generator_thread_pool import DataGenerationManager
from gui.threads.ai_strategy_thread_pool import StrategyGeneratorTask
import datetime,os,json
from core.ai_generator import ZhipuAIHandler


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.table_match_worker = None
        self.generator_manager = None
        self.console = None
        self.fields_table = None
        self.table_widget = None
        self.match_button = None
        self.match_mode = None
        self.match_input = None
        self.stop_button = None
        self.generate_button = None
        self.ai_strategy_button = None
        self.settings_button = None
        self.edit_connection_button = None
        self.new_connection_button = None
        self.data_generator_pool = None
        self.setWindowIcon(QIcon("assets/icon.ico"))
        self.connector_pool = DatabaseConnectorPool()

        # 初始化核心属性
        self.db_combo = None
        self.config_manager = ConfigManager()
        self.config = self.config_manager.load_config()
        self.connections = self.config.get("db_connections", {})
        self.init_ui()

    def init_ui(self):
        """初始化界面"""
        self.setWindowTitle("AI数据生成器")
        self.setGeometry(100, 100, 1200, 600)  # 调整窗口宽度以适应两个表格

        main_layout = QVBoxLayout()

        # 数据库连接管理部分
        db_connection_layout = QHBoxLayout()
        self.db_combo = QComboBox()
        self.db_combo.addItems(self.connections.keys())

        self.new_connection_button = QPushButton("新增连接")
        self.new_connection_button.clicked.connect(self.add_connection_dialog)
        self.new_connection_button.setIcon(QIcon("assets/icon/add.png"))
        self.edit_connection_button = QPushButton("编辑连接")
        self.edit_connection_button.clicked.connect(self.edit_connection_dialog)
        self.edit_connection_button.setIcon(QIcon("assets/icon/edit.png"))

        db_connection_layout.addWidget(QLabel("数据库连接："))
        db_connection_layout.addWidget(self.db_combo)
        db_connection_layout.addWidget(self.new_connection_button)
        db_connection_layout.addWidget(self.edit_connection_button)

        self.settings_button = QPushButton("系统设置")
        self.settings_button.clicked.connect(self.open_settings_dialog)
        self.settings_button.setIcon(QIcon("assets/icon/settings.png"))
        db_connection_layout.addWidget(self.settings_button)

        self.ai_strategy_button = QPushButton("AI策略配置")
        self.ai_strategy_button.clicked.connect(self.generate_ai_strategy)
        self.ai_strategy_button.setIcon(QIcon("assets/icon/ai.png"))
        db_connection_layout.addWidget(self.ai_strategy_button)

        # 添加“资助”按钮
        self.sponsor_button = QPushButton("资助")
        self.sponsor_button.setIcon(QIcon("assets/icon/bag.png"))  # 设置图标
        self.sponsor_button.clicked.connect(self.show_sponsor_dialog)  # 绑定事件
        db_connection_layout.addWidget(self.sponsor_button)

        # 添加右上角的“生成”按钮
        self.generate_button = QPushButton("开始生成")
        self.generate_button.clicked.connect(self.generate_test_data)
        self.generate_button.setIcon(QIcon("assets/icon/start.png"))

        self.stop_button = QPushButton("停止生成")
        self.stop_button.clicked.connect(self.stop_test_data_generation)
        self.stop_button.setIcon(QIcon("assets/icon/stop.png"))

        db_connection_layout.addStretch()
        db_connection_layout.addWidget(self.generate_button)
        db_connection_layout.addWidget(self.stop_button)

        # 匹配条件输入部分
        match_input_layout = QHBoxLayout()
        self.match_input = QLineEdit()
        self.match_mode = QComboBox()
        self.match_mode.addItems(["前缀匹配", "后缀匹配", "模糊匹配"])
        self.match_button = QPushButton("匹配")
        self.match_button.clicked.connect(self.start_match_tables)
        self.match_button.setIcon(QIcon("assets/icon/find.png"))

        match_input_layout.addWidget(QLabel("匹配关键字："))
        match_input_layout.addWidget(self.match_input)
        match_input_layout.addWidget(QLabel("匹配模式："))
        match_input_layout.addWidget(self.match_mode)
        match_input_layout.addWidget(self.match_button)

        # 左侧表格显示部分
        self.table_widget = QTableWidget()
        self.table_widget.setColumnCount(4)
        self.table_widget.setHorizontalHeaderLabels(["双击全选", "表名", "记录数", "字段数"])
        self.table_widget.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.table_widget.setSortingEnabled(True)
        self.table_widget.itemSelectionChanged.connect(self.update_fields_table)
        # 绑定双击事件
        self.table_widget.horizontalHeader().sectionDoubleClicked.connect(self.handle_header_double_click)

        # 右侧字段显示表格
        self.fields_table = QTableWidget()
        self.fields_table.setColumnCount(4)
        self.fields_table.setHorizontalHeaderLabels(["字段名", "数据类型", "生成策略", "生成"])
        self.fields_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.fields_table.setSortingEnabled(True)

        # 添加“更新”按钮
        self.update_fields_button = QPushButton("保存字段策略")
        self.update_fields_button.clicked.connect(self.save_field_generation_strategies)
        self.update_fields_button.setMinimumWidth(200)  # 设置最小宽度
        self.update_fields_button.setMaximumWidth(300)  # 设置最大宽度
        self.update_fields_button.setIcon(QIcon("assets/icon/update.png"))

        # 在字段表格顶部增加一个垂直布局
        fields_layout = QVBoxLayout()
        fields_layout.addWidget(self.update_fields_button)
        fields_layout.addWidget(self.fields_table)

        # 创建一个嵌套 QWidget，便于布局管理
        fields_widget_container = QWidget()
        fields_widget_container.setLayout(fields_layout)

        # 使用 QSplitter 分隔两个表格
        table_splitter = QSplitter(Qt.Horizontal)
        table_splitter.addWidget(self.table_widget)
        table_splitter.addWidget(fields_widget_container)
        table_splitter.setSizes([600, 600])  # 初始宽度分配

        # 控制台窗口
        self.console = QTextEdit()
        self.console.setReadOnly(True)
        self.console.setContextMenuPolicy(Qt.CustomContextMenu)
        self.console.customContextMenuRequested.connect(self.show_console_menu)

        # 使用 QSplitter 分隔表格和控制台
        splitter = QSplitter(Qt.Vertical)
        splitter.addWidget(table_splitter)
        splitter.addWidget(self.console)
        splitter.setSizes([500, 50])  # 表格高度500，控制台高度50

        # 布局整合
        main_layout.addLayout(db_connection_layout)
        main_layout.addLayout(match_input_layout)
        main_layout.addWidget(splitter)

        central_widget = QWidget()
        central_widget.setLayout(main_layout)
        self.setCentralWidget(central_widget)

    def show_sponsor_dialog(self):
        """显示资助对话框"""
        dialog = QDialog(self)
        dialog.setWindowTitle("谢谢您的资助")
        dialog.setFixedSize(600, 600)  # 设置正方形大小

        # 创建垂直布局
        layout = QVBoxLayout()

        # 添加二维码图片
        qr_label = QLabel()
        qr_pixmap = QPixmap("assets/wx.jpg")  # 替换为你的二维码图片路径
        qr_pixmap = qr_pixmap.scaled(500, 500, Qt.KeepAspectRatio)  # 调整图片大小
        qr_label.setPixmap(qr_pixmap)
        qr_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(qr_label)

        # 添加邮箱地址
        email_label = QLabel("需求反馈: ok_ai@outlook.com")  # 替换为你的邮箱地址
        email_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(email_label)

        # 添加关闭按钮
        close_button = QPushButton("关闭")
        close_button.clicked.connect(dialog.accept)
        layout.addWidget(close_button)

        dialog.setLayout(layout)
        dialog.exec_()


    def update_fields_table(self):
        """更新右侧字段信息表格"""
        selected_row = self.table_widget.currentRow()  # 获取当前选中的行索引
        if selected_row == -1:  # 如果没有选中任何行
            self.clear_fields_table()
            return

        # 获取表名列内容
        selected_table_name_item = self.table_widget.item(selected_row, 1)  # 表名在第2列 (索引1)
        if not selected_table_name_item:  # 如果表名单元格为空
            self.clear_fields_table()
            return

        selected_table_name = selected_table_name_item.text()
        current_connector = self.get_current_db_connector().get_connector_name()
        strategy_save_path = self.config.get("strategy_save_path", "./strategies")
        file_name = f"{current_connector}_{selected_table_name}.json"
        file_path = os.path.join(strategy_save_path, file_name)

        self.clear_fields_table()
        if os.path.exists(file_path):
            self.load_fields_from_strategy_file(file_path)
        else:
            self.load_fields_from_database(selected_table_name)

    def clear_fields_table(self):
        """清空字段表格"""
        self.fields_table.clearContents()
        self.fields_table.setRowCount(99)
        self.fields_table.setColumnCount(4)
        self.fields_table.setHorizontalHeaderLabels(["字段名", "数据类型", "生成策略", "生成"])

    def load_fields_from_strategy_file(self, file_path):
        """从策略文件中加载字段信息"""
        try:
            with open(file_path, "r", encoding="utf-8") as file:
                content = file.read()
                strategy = json.loads(content)  # 尝试解析为 JSON

            if not isinstance(strategy, dict):
                raise ValueError(f"策略文件 {file_path} 的内容格式不正确，必须是字典")

            self.fields_table.setRowCount(len(strategy))
            for row, (field_name, details) in enumerate(strategy.items()):
                # 字段名
                self.fields_table.setItem(row, 0, QTableWidgetItem(field_name))

                # 数据类型
                data_type = details.get("data_type", "未知")
                self.fields_table.setItem(row, 1, QTableWidgetItem(data_type))

                # 生成策略
                strategy_text = details.get("strategy", "无策略")
                self.fields_table.setItem(row, 2, QTableWidgetItem(strategy_text))

                # 是否生成
                is_gen = details.get("is_gen", False)
                checkbox = QCheckBox()
                checkbox.setChecked(is_gen)
                container = QWidget()
                layout = QHBoxLayout(container)
                layout.addWidget(checkbox)
                layout.setAlignment(Qt.AlignCenter)
                layout.setContentsMargins(0, 0, 0, 0)
                self.fields_table.setCellWidget(row, 3, container)

            self.append_console(f"从策略文件加载字段信息成功：{file_path}")
        except Exception as e:
            self.append_console(f"加载策略文件失败：{e}")

    def load_fields_from_database(self, table_name):
        """从数据库中加载字段信息"""
        try:
            # 获取当前数据库连接器
            db_connector = self.get_current_db_connector()

            # 从数据库中获取字段信息
            fields_info = db_connector.get_table_fields(table_name)

            # 设置表格行数
            self.fields_table.setRowCount(len(fields_info))

            for row, field in enumerate(fields_info):
                # 字段名
                field_name = field["FieldName"]
                self.fields_table.setItem(row, 0, QTableWidgetItem(field_name))

                # 数据类型
                data_type = field["DataType"]
                self.fields_table.setItem(row, 1, QTableWidgetItem(data_type))

                # 生成策略 (默认为无策略)
                self.fields_table.setItem(row, 2, QTableWidgetItem(""))

                # 是否生成 (默认为 False)
                is_gen = field.get("IS_GEN", False)
                checkbox = QCheckBox()
                checkbox.setChecked(is_gen)
                container = QWidget()
                layout = QHBoxLayout(container)
                layout.addWidget(checkbox)
                layout.setAlignment(Qt.AlignCenter)
                layout.setContentsMargins(0, 0, 0, 0)
                self.fields_table.setCellWidget(row, 3, container)

            self.append_console(f"从数据库加载字段信息成功：{table_name}")

        except Exception as e:
            self.append_console(f"获取字段信息失败：{e}")

    def save_field_generation_strategies(self):
        """
        保存用户在字段表格中编辑的生成策略到配置文件。
        """
        try:
            # 获取当前选中表的信息
            selected_row = self.table_widget.currentRow()
            if selected_row == -1:
                QMessageBox.warning(self, "警告", "请先选择一个表！")
                return

            table_name = self.table_widget.item(selected_row, 1).text()
            current_connector = self.get_current_db_connector().get_connector_name()
            strategy_save_path = self.config.get("strategy_save_path", "./strategies")
            file_name = f"{current_connector}_{table_name}.json"
            file_path = os.path.join(strategy_save_path, file_name)

            # 读取字段表中的信息
            strategies = {}
            for row in range(self.fields_table.rowCount()):
                field_name_item = self.fields_table.item(row, 0)
                data_type_item = self.fields_table.item(row, 1)
                strategy_item = self.fields_table.item(row, 2)
                checkbox_widget = self.fields_table.cellWidget(row, 3)

                if field_name_item is None:
                    continue

                field_name = field_name_item.text()
                data_type = data_type_item.text() if data_type_item else "未知"
                strategy = strategy_item.text() if strategy_item else "无策略"
                is_gen = checkbox_widget.findChild(QCheckBox).isChecked() if checkbox_widget else False

                strategies[field_name] = {
                    "data_type": data_type,
                    "strategy": strategy,
                    "is_gen": is_gen
                }

            # 保存到文件
            os.makedirs(strategy_save_path, exist_ok=True)
            with open(file_path, "w", encoding="utf-8") as file:
                json.dump(strategies, file, ensure_ascii=False, indent=4)

            QMessageBox.information(self, "成功", f"策略已保存到文件：{file_path}")
            self.append_console(f"策略已成功保存：{file_path}")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"保存策略失败：{str(e)}")
            self.append_console(f"保存策略失败：{str(e)}")

    def open_settings_dialog(self):
        """打开系统设置对话框"""
        dialog = SettingsDialog(self.config_manager)
        dialog.exec_()

    def get_current_db_connector(self):
        """
        返回当前选中的数据库连接实例，动态选择合适的 Connector。
        """
        db_name = self.db_combo.currentText()
        if not db_name:
            raise ValueError("请选择数据库连接！")

        db_config = self.connections.get(db_name)
        if not db_config:
            raise ValueError(f"未找到名为 {db_name} 的数据库配置！")

        # 获取或创建连接池
        return self.connector_pool.get_or_create_connector(db_name, db_config)

    def generate_ai_strategy(self):
        """
        启动字段生成策略线程池。
        """
        selected_rows = self.get_selected_tables()
        if not selected_rows:
            QMessageBox.warning(self, "警告", "请至少选择一个数据表！")
            return

        try:
            ai_module = ZhipuAIHandler()
            db_connector = self.get_current_db_connector()
            thread_pool = QThreadPool.globalInstance()

            ai_thread_count = int(self.config.get("ai_thread_count", 5))  # 从配置中获取线程数量
            thread_pool.setMaxThreadCount(ai_thread_count)
            strategy_save_path = self.config.get("strategy_save_path", "./strategies")

            for row, table_name in selected_rows:
                task = StrategyGeneratorTask(
                    db_connector=db_connector,
                    ai_module=ai_module,
                    table_name=table_name,
                    row=row,
                    strategy_save_path=strategy_save_path
                )

                task.signals.status_signal.connect(self.mark_table_row_with_color)
                task.signals.progress_signal.connect(self.append_console)
                task.signals.error_signal.connect(self.handle_strategy_error)
                thread_pool.start(task)
        except Exception as e:
            QMessageBox.critical(self, "错误", f"AI制定生成策略失败：{str(e)}")


    @pyqtSlot(str, str)
    def handle_strategy_error(self, table_name, error_message):
        """
        处理生成策略的错误。
        """
        self.append_console(f"表 {table_name} 的生成策略失败：{error_message}")

    def add_connection_dialog(self):
        """弹出新增数据库连接的对话框"""
        dialog = ConnectionDialog(self, is_edit=False)
        if dialog.exec_():
            connection_name, connection_info = dialog.get_connection_data()
            if connection_name in self.connections:
                QMessageBox.warning(self, "警告", "连接名称已存在，请使用其他名称！")
                return
            self.connections[connection_name] = connection_info
            self.config["db_connections"] = self.connections
            self.config_manager.save_config(self.config)
            self.db_combo.addItem(connection_name)
            QMessageBox.information(self, "成功", "数据库连接已新增！")

    def edit_connection_dialog(self):
        """弹出编辑数据库连接的对话框"""
        selected_connection = self.db_combo.currentText()
        if not selected_connection:
            QMessageBox.warning(self, "警告", "请选择要编辑的数据库连接！")
            return
        connection_info = self.connections[selected_connection]
        dialog = ConnectionDialog(
            self,
            is_edit=True,
            connection_name=selected_connection,
            connection_info=connection_info
        )
        if dialog.exec_():
            connection_name, connection_info = dialog.get_connection_data()
            self.connections[connection_name] = connection_info
            self.config["db_connections"] = self.connections
            self.config_manager.save_config(self.config)
            QMessageBox.information(self, "成功", "数据库连接已更新！")

    def start_match_tables(self):
        """启动表匹配线程"""
        # 先重置界面和变量
        self.reset()

        keyword = self.match_input.text()
        match_mode = self.match_mode.currentText()
        db_config = self.connections.get(self.db_combo.currentText(), {})

        if not keyword:
            QMessageBox.warning(self, "警告", "请输入匹配关键字！")
            return

        if not db_config:
            QMessageBox.warning(self, "警告", "请选择一个数据库连接！")
            return

        self.table_match_worker = TableMatchWorker(self.get_current_db_connector(), keyword, match_mode)
        self.table_match_worker.progress_signal.connect(self.append_console)
        self.table_match_worker.match_done_signal.connect(self.populate_table)
        self.table_match_worker.start()

    def handle_header_double_click(self, index):
        """
        处理表头双击事件
        :param index: 双击的列索引
        """
        if index == 0:  # 如果双击的是 "双击全选" 列
            all_checked = all(
                self.table_widget.item(row, 0).checkState() == Qt.Checked
                for row in range(self.table_widget.rowCount())
            )
            new_state = Qt.Unchecked if all_checked else Qt.Checked

            # 更新所有复选框的状态
            for row in range(self.table_widget.rowCount()):
                item = self.table_widget.item(row, 0)
                if item is not None:
                    item.setCheckState(new_state)

    def reset(self):
        """重置界面和变量"""
        # 清空表格数据
        self.table_widget.clearContents()
        self.table_widget.setRowCount(0)

        # 停止可能仍在运行的工作线程
        if hasattr(self, "table_match_worker") and self.table_match_worker:
            if self.table_match_worker.isRunning():
                self.table_match_worker.terminate()
                self.table_match_worker.wait()
                self.append_console("重置时停止了正在运行的表匹配线程。")
            self.table_match_worker = None

        # 其他重置逻辑
        self.append_console("已重置界面和变量。")

    def populate_table(self, tables_info):
        """填充表格数据"""
        # 清除旧数据
        self.table_widget.clearContents()
        self.table_widget.setRowCount(0)

        self.table_widget.setRowCount(len(tables_info))
        for row, (table_name, row_count, column_count) in enumerate(tables_info):
            # 第一列：复选框
            checkbox_item = QTableWidgetItem()
            checkbox_item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
            checkbox_item.setCheckState(Qt.Unchecked)
            checkbox_item.setTextAlignment(Qt.AlignCenter)
            self.table_widget.setItem(row, 0, checkbox_item)

            # 第二列：表名
            table_name_item = QTableWidgetItem(table_name)
            table_name_item.setFlags(table_name_item.flags() & ~Qt.ItemIsEditable)
            self.table_widget.setItem(row, 1, table_name_item)

            # 第三列：记录数
            row_count_item = QTableWidgetItem(str(row_count))
            row_count_item.setFlags(row_count_item.flags() & ~Qt.ItemIsEditable)
            self.table_widget.setItem(row, 2, row_count_item)

            # 第四列：字段数
            column_count_item = QTableWidgetItem(str(column_count))
            column_count_item.setFlags(column_count_item.flags() & ~Qt.ItemIsEditable)
            self.table_widget.setItem(row, 3, column_count_item)

        self.table_widget.viewport().update()  # 刷新表格

    def get_selected_tables(self):
        selected_tables = [
            (row, self.table_widget.item(row, 1).text())
            for row in range(self.table_widget.rowCount())
            if self.table_widget.item(row, 0).checkState() == Qt.Checked
        ]
        return selected_tables


    def generate_test_data(self):

        selected_tables = self.get_selected_tables()
        if not selected_tables:
            QMessageBox.warning(self, "警告", "请至少选择一个数据表！")
            return

        db_config = self.connections.get(self.db_combo.currentText(), {})
        if not db_config:
            QMessageBox.warning(self, "警告", "请选择一个数据库连接！")
            return

        # 初始化管理器
        self.generator_manager = DataGenerationManager(
            selected_tables,
            self.get_current_db_connector(),
            config=self.config
        )

        # 启动任务
        self.generator_manager.start(
            start_signal=self.mark_table_row_with_color,
            progress_signal=self.update_row_status
        )

    def mark_table_row_with_color(self, row, color):
        for col in range(self.table_widget.columnCount()):
            item = self.table_widget.item(row, col)
            if not item:  # 如果单元格为空，创建一个新项
                item = QTableWidgetItem()
                self.table_widget.setItem(row, col, item)
            item.setBackground(QColor(color))
        self.table_widget.viewport().update()


    def update_row_status(self, row, process_result, status):
        """更新行状态"""
        if status == "success":
            current_records = int(self.table_widget.item(row, 2).text())
            if process_result['success_count'] > 0:
                for col in range(self.table_widget.columnCount()):
                    item = self.table_widget.item(row, col)
                    item.setBackground(QColor("white"))
                    item.setForeground(QColor("green"))
                self.table_widget.setItem(row, 2,
                                          QTableWidgetItem(str(current_records + process_result['success_count'])))
                console_log = (
                    f"\n表[{process_result['table']}]处理成功，"
                    f"追加了[{process_result['success_count']}]条测试数据"
                )
                self.append_console(console_log)
            else:
                for col in range(self.table_widget.columnCount()):
                    item = self.table_widget.item(row, col)
                    item.setBackground(QColor("white"))
                    item.setForeground(QColor("red"))
                failure_details = process_result['failure_details']
                console_log = (
                    f"\n表[{process_result['table']}]处理失败，"
                    f"[{process_result['failure_count']}]条测试数据插入失败:\n"
                    f"失败详情: {failure_details}"
                )
                self.append_console(console_log)
        elif status == "error":
            for col in range(self.table_widget.columnCount()):
                item = self.table_widget.item(row, col)
                item.setBackground(QColor("white"))
                item.setForeground(QColor("red"))
            console_log = (
                f"\n表[{process_result['table']}]处理失败："
                f"{process_result['failure_details']}"
            )
            self.append_console(console_log)


    def stop_test_data_generation(self):
        self.generator_manager.stop()

    def show_console_menu(self, position):
        """显示控制台右键菜单"""
        menu = QMenu(self.console)
        clear_action = menu.addAction("清除")
        clear_action.triggered.connect(self.clear_console)
        menu.exec_(self.console.mapToGlobal(position))

    def clear_console(self):
        """清除控制台内容"""
        self.console.clear()

    def append_console(self, message):
        current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.console.append(f"[{current_time}]: {message}")
        self.console.ensureCursorVisible()

    def closeEvent(self, event):
        # 弹出确认对话框
        reply = QMessageBox.question(
            self,
            "确认退出",
            "确定要关闭窗口吗？",
            QMessageBox.Yes | QMessageBox.No,
            QMessageBox.No
        )

        if reply == QMessageBox.Yes:
            self.connector_pool.close_all()
            super().closeEvent(event)
            event.accept()  # 确认关闭
        else:
            event.ignore()  # 取消关闭


